// Random Numbers (随机数) 示例
// 演示 Pascal 中随机数生成的各种用法
program p_44_random_numbers;

{$mode objfpc}{$H+}
// {$mode objfpc} 启用 Object Pascal 模式
// {$H+} 启用长字符串支持（AnsiString）

// 引入单元文件
uses
  SysUtils,      // 系统工具单元
  Math;          // 数学单元

// 基本随机数生成示例
procedure BasicRandomNumberGeneration;
var
  i: Integer;
  randomFloat: Double;
begin
  WriteLn('1. 基本随机数生成:');
  
  // 生成0到1之间的浮点随机数
  WriteLn('  0到1之间的浮点随机数:');
  for i := 1 to 5 do
  begin
    randomFloat := Random;
    WriteLn('    随机数 ', i, ': ', randomFloat:0:6);
  end;
end;

// 指定范围随机数生成示例
procedure RangeRandomNumberGeneration;
var
  i: Integer;
  randomInt: Integer;
begin
  WriteLn('2. 指定范围随机数生成:');
  
  // 生成0到99之间的整数随机数
  WriteLn('  0到99之间的整数随机数:');
  for i := 1 to 10 do
  begin
    randomInt := Random(100);
    Write('    ', randomInt:3);
    if (i mod 5) = 0 then
      WriteLn;
  end;
  
  WriteLn;
  
  // 生成10到50之间的整数随机数
  WriteLn('  10到50之间的整数随机数:');
  for i := 1 to 10 do
  begin
    randomInt := Random(41) + 10;  // 41个可能值(0-40) + 10 = 10-50
    Write('    ', randomInt:3);
    if (i mod 5) = 0 then
      WriteLn;
  end;
  
  WriteLn;
  
  // 生成浮点随机数
  WriteLn('  0到10之间的浮点随机数:');
  for i := 1 to 5 do
  begin
    randomFloat := Random * 10;
    WriteLn('    随机数 ', i, ': ', randomFloat:0:2);
  end;
end;

// 随机数种子控制示例
procedure RandomSeedControl;
var
  i: Integer;
  savedSeed: Integer;
begin
  WriteLn('3. 随机数种子控制:');
  
  // 保存当前种子
  savedSeed := RandSeed;
  
  // 使用固定种子生成随机数
  RandSeed := 12345;
  WriteLn('  使用种子12345生成的随机数:');
  for i := 1 to 5 do
    Write('    ', Random(100):3);
  WriteLn;
  
  // 使用相同种子再次生成
  RandSeed := 12345;
  WriteLn('  使用相同种子再次生成:');
  for i := 1 to 5 do
    Write('    ', Random(100):3);
  WriteLn;
  
  // 恢复原始种子
  RandSeed := savedSeed;
  
  // 使用Randomize初始化种子
  WriteLn('  使用Randomize初始化种子:');
  Randomize;
  for i := 1 to 5 do
    Write('    ', Random(100):3);
  WriteLn;
end;

// 随机选择和排列示例
procedure RandomSelectionAndShuffling;
var
  colors: array[0..5] of String = ('红色', '绿色', '蓝色', '黄色', '紫色', '橙色');
  numbers: array[0..9] of Integer = (1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
  i, randomIndex: Integer;
begin
  WriteLn('4. 随机选择和排列:');
  
  // 随机选择颜色
  WriteLn('  随机选择颜色:');
  for i := 1 to 5 do
  begin
    randomIndex := Random(6);
    WriteLn('    选择 ', i, ': ', colors[randomIndex]);
  end;
  
  WriteLn;
  
  // 随机打乱数字数组
  WriteLn('  随机打乱数字数组:');
  Write('    原始数组: ');
  for i := 0 to 9 do
    Write(numbers[i]:3);
  WriteLn;
  
  // 使用Fisher-Yates洗牌算法
  for i := 9 downto 1 do
  begin
    randomIndex := Random(i + 1);
    // 交换元素
    var temp := numbers[i];
    numbers[i] := numbers[randomIndex];
    numbers[randomIndex] := temp;
  end;
  
  Write('    打乱后:   ');
  for i := 0 to 9 do
    Write(numbers[i]:3);
  WriteLn;
end;

// 概率分布随机数示例
procedure ProbabilityDistributionRandom;
var
  i: Integer;
  value: Integer;
  count: array[0..9] of Integer;
begin
  WriteLn('5. 概率分布随机数:');
  
  // 初始化计数器
  for i := 0 to 9 do
    count[i] := 0;
  
  // 生成大量随机数并统计分布
  WriteLn('  生成1000个0-9的随机数并统计分布:');
  for i := 1 to 1000 do
  begin
    value := Random(10);
    Inc(count[value]);
  end;
  
  // 显示分布结果
  for i := 0 to 9 do
  begin
    Write('    ', i, ': ');
    // 显示直方图
    var barLength := count[i] div 20;  // 每20个单位显示一个星号
    var j: Integer;
    for j := 1 to barLength do
      Write('*');
    WriteLn(' (', count[i], ')');
  end;
end;

// 随机数在实际应用中的使用示例
procedure PracticalRandomNumberUsage;
var
  i: Integer;
  diceRoll: Integer;
  coinFlip: Integer;
  randomName: array[0..4] of String = ('张三', '李四', '王五', '赵六', '钱七');
begin
  WriteLn('6. 随机数在实际应用中的使用:');
  
  // 模拟掷骰子
  WriteLn('  模拟掷骰子 (6面骰) - 10次:');
  for i := 1 to 10 do
  begin
    diceRoll := Random(6) + 1;  // 1-6
    Write('    第', i, '次: ', diceRoll);
    if i < 10 then
      Write(', ')
    else
      WriteLn;
  end;
  
  WriteLn;
  
  // 模拟抛硬币
  WriteLn('  模拟抛硬币 - 10次:');
  for i := 1 to 10 do
  begin
    coinFlip := Random(2);  // 0或1
    if coinFlip = 0 then
      Write('正面')
    else
      Write('反面');
    
    if i < 10 then
      Write(', ')
    else
      WriteLn;
  end;
  
  WriteLn;
  
  // 随机选择姓名
  WriteLn('  随机选择姓名 - 5次:');
  for i := 1 to 5 do
  begin
    var randomIndex := Random(5);
    WriteLn('    选择 ', i, ': ', randomName[randomIndex]);
  end;
  
  WriteLn;
  
  // 生成随机密码 (简单示例)
  WriteLn('  生成简单随机密码:');
  var password: String = '';
  var chars: String = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  for i := 1 to 8 do
  begin
    var randomIndex := Random(Length(chars)) + 1;
    password := password + chars[randomIndex];
  end;
  WriteLn('    生成的密码: ', password);
end;

// 程序主入口
begin
  WriteLn('=== Pascal 随机数示例 ===');
  WriteLn;
  
  // 1. 基本随机数生成
  BasicRandomNumberGeneration;
  
  WriteLn;
  
  // 2. 指定范围随机数生成
  RangeRandomNumberGeneration;
  
  WriteLn;
  
  // 3. 随机数种子控制
  RandomSeedControl;
  
  WriteLn;
  
  // 4. 随机选择和排列
  RandomSelectionAndShuffling;
  
  WriteLn;
  
  // 5. 概率分布随机数
  ProbabilityDistributionRandom;
  
  WriteLn;
  
  // 6. 随机数在实际应用中的使用
  PracticalRandomNumberUsage;
  
  WriteLn;
  WriteLn('演示了 Pascal 中随机数生成的各种用法');
  
  // 等待用户按键，防止程序窗口立即关闭
  ReadLn;
end.